// 8位宽字符
#define PCRE2_CODE_UNIT_WIDTH 8

#include<stdio.h>
#include<string.h>
#include<pcre2.h>

// 排序比较函数
int cmp(const void *p, const void *q);
// 输出重复数字
void print_repetition(int n);

int main()
{
    int i;
    int a[] = {282112, 2822, 1234, 112355, 12345678};

    for(i = 0; i < sizeof(a) / sizeof(a[0]); i++)
    {
        printf("%d: ", a[i]);
        print_repetition(a[i]);
    }

    return 0;
}

// 输出重复数字
void print_repetition(int n)
{
    // 数字字符串缓存
    char s[8] = {0};

    int flag = 0;

    // 正则缓存(编译后的正则表达式)
    pcre2_code *re;
    // 正则匹配返回值
    int rc;

    // 错误代码
    int errornumber;
    // 错误偏移量
    PCRE2_SIZE erroroffset;

    // 匹配寄存器(各分组匹配起始与结束位置)
    pcre2_match_data *match_data;

    // 正则表达式
    PCRE2_SPTR pattern;
    // 输入字符串
    PCRE2_SPTR subject;

    // 判断整数有效性
    if(n <= 0 || n > 10000000)
    {
        printf("Invalid input\n");
        return;
    }

    if(n > 0 && n < 10)
    {
        printf("No repeated numbers.\n");
        return;
    }

    // 将整数转换为字符串并排序
    sprintf(s, "%d", n);
    qsort(s, strlen(s), 1, cmp);

    // 正则表达式(注意用\\转义)
    pattern = (PCRE2_SPTR)"([0-9])\\1+";
    subject = (PCRE2_SPTR)s;

    // 编译正则表达式
    re = pcre2_compile(pattern,               /* 模式(正则表达式) */
                       PCRE2_ZERO_TERMINATED, /* 模式长度('\0'终止字符串) */
                       0,                     /* 默认选项 */
                       &errornumber,          /* 错误编码 */
                       &erroroffset,          /* 错误信息偏移量 */
                       NULL);                 /* 上下文，一般取NULL */
    /* 编译失败处理. */
    if (re == NULL)
    {
        PCRE2_UCHAR buffer[256];
        pcre2_get_error_message(errornumber, buffer, sizeof(buffer));
        printf("PCRE2 compilation failed at offset %d: %s\n",
               (int)erroroffset, buffer);
        exit(EXIT_FAILURE);
    }

    // 构造匹配寄存器以记录匹配结果
    match_data = pcre2_match_data_create_from_pattern(re, NULL);

    flag = 0;

    // 匹配
    rc = pcre2_match(re,                    // 正则缓存(正则表达式编译结果)
                     subject,               // 待匹配字符串
                     PCRE2_ZERO_TERMINATED, // 待匹配字符串长度(以'\0'结尾)
                     0,                     // 开始匹配偏移量
                     0,                     // 选项
                     match_data,            // 匹配寄存器
                     NULL                   // 上下文，一般取NULL
                     );

    // 得到匹配结果向量(按开始结束的方式记录各分组匹配结果，0表示group 0)
    PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);

    // 输出匹配结果
    while(rc > 0)
    {
        putchar(subject[ovector[0]]);
        putchar(' ');

        // 置标志
        flag = 1;

        // 从上次匹配末尾再次开始匹配(或用input += ovector[1];)
        subject += ovector[1];
        rc = pcre2_match(re, subject, PCRE2_ZERO_TERMINATED,
                         0, 0, match_data, NULL);

        // 获取匹配寄存器
        ovector = pcre2_get_ovector_pointer(match_data);
    }

    // 释放内存
    pcre2_match_data_free(match_data);
    pcre2_code_free(re);

    // 无重复数字
    if(!flag)
    {
        printf("No repeated numbers.\n");
    }
    else
    {
        printf("\n");
    }
}

int cmp(const void *p, const void *q)
{
    char ch_p = *((char*)p);
    char ch_q = *((char*)q);

    return (ch_p > ch_q) - (ch_p < ch_q);
}
